﻿package igz.fleaxy
{
	import flash.display.Stage;
	import flash.events.IOErrorEvent;
	import flash.text.Font;
	import igz.fleaxy.configuration.ConfigurationManager;
	import igz.fleaxy.css.CssManager;
	import igz.fleaxy.events.CommEvent;
	import igz.fleaxy.locale.LocaleManager;
	import igz.fleaxy.net.Comm;
	import igz.fleaxy.net.CommResponseType;
	import igz.fleaxy.util.ObjectUtil;

	/**
	 * @author Intelygenz | www.intelygenz.com
	 * @version 0.501
	 */
	public class Fleaxy {
		/**
		 * Fleaxy version in use
		 */
		static public const $VERSION : Number = 0.000;

		/**
		 * Stage
		 *
		 * Pantalla o Stage principal de la aplicación
		 */
		public var _Stage : Stage;
		public function get $Stage () : Stage {
			return _Stage;
		}

		/**
		 * Fleaxy instance
		 *
		 *   Instancia de Fleaxy, que actua siempre como singleton
		 */
		static public var _Current : Fleaxy;
		static public function get $Current() : Fleaxy {
			if ( _Current == null ) {
				_Current = new Fleaxy();
			}
			return _Current;
		}
		
		static public function get $FleaxyIsCharged() : Boolean {
			if (_Current == null)
				return false;
			else
				return true;
		}

		/**
		 * ConfigurationManager
		 *
		 *   Instancia del gestor de configuración
		 */
		public var _ConfigurationManager : ConfigurationManager;
		public function get $ConfigurationManager () : ConfigurationManager {
			return _ConfigurationManager;
		}

		/**
		 * LocaleManager
		 *
		 *   Gestor de idioma
		 */
		public var _LocaleManager : LocaleManager;
		public function get $LocaleManager () : LocaleManager {
			return _LocaleManager;
		}

		/**
		 * CssManager
		 *
		 *   Gestor de estilos
		 */
		public var _CssManager : CssManager;
		public function get $CssManager () : CssManager {
			return _CssManager;
		}

		/**
		 * Options
		 *
		 *    Opciones
		 */
		private var _Settings : Object;

		/**
		 *   Inicializa Fleaxy
		 *
		 * @param	p_stage  Stage principal donde se ejecuta
		 * @param	p_settings Opciones o settings
		 */
		public function Fleaxy() {

		}
		
		/**
		 * Initialize embed fonts, load language files...
		 * @param	p_stage : Stage
		 * @param	p_settings :{ embedFonts : [ EmbedFontClass1, EmbedFontClass2, ... ]
		 * 			, iso639 : String
		 * 			, onComplete : function () { }
		 * 			, uriConfigXml : String
		 * 			}
		 * @example
		 * 			Fleaxy.$Init( stage
		 * 			, { embedFonts : [Trebuchet_N]
		 *				, iso639 	 : "ES"
		 *				, onComplete : _OnInitComplete
		 *				}
		 *			);
		 */
		public function $Init(p_stage:Stage, p_settings:Object = null) : void {
			_Stage = p_stage;
			_Settings = { "uriConfigXml"  : swfPath + "./config.xml"
						, "embedIso639": { }
						};
			ObjectUtil.$Merge( p_settings, _Settings );

			var swfUri:String  = _Stage.loaderInfo.url;
			var swfPath:String = "";
			if ( swfUri != "" ) {
				swfUri  = unescape(swfUri);
				swfPath = swfUri.substring(0, swfUri.lastIndexOf("/"))+"/";
			}

			// Registra fuentes embebidas para poder usarlas en tiempo de ejecución
			for each ( var fontClass:Class in _Settings.embedFonts) {
				Font.registerFont(fontClass);
			}

			_LocaleManager = new LocaleManager();

			_CssManager = new CssManager();
			
			if ( _Settings["embedConfigXml"] != null ) {
				_LoadConfigXML( _Settings["embedConfigXml"] as XML );
			}
			else {
				Comm.$Get(_Settings["uriConfigXml"]
					 , { onComplete : _ConfigXml_OnComplete, onIOError : _ConfigXml_OnIOError }
					 );
			}

		}
		
		/**
		 * Función que configura la aplicación a partir del XML de configuración. Se le pasa un "CommEvent" que
		 * se ejecutaró cuando se complete la configuración. En caso de que falle devolveró un error por consola
		 *
		 * @param	p_commEvent CommEvent que se ejecutaró cuando termine
		 */
		private function _ConfigXml_OnComplete(p_commEvent:CommEvent) : void {
		if ( p_commEvent.$CommResponseType == CommResponseType.$XML ) {
				_LoadConfigXML( p_commEvent.$ResponseXML );
			}
			else {
				trace("El archivo cargado no es un fichero XML de configuración válido");
			}
		}
		
		/**
		 * Función que es llamada dentro de "_ConfigXml_OnComplete" y configura diversos aspectos de la aplicación como los css,
		 * el idioma u otros elementos
		 *
		 * @param	p_configXML
		 */
		private function _LoadConfigXML ( p_configXML:XML ) : void {
			_ConfigurationManager = new ConfigurationManager( p_configXML );
			
			if ( _Settings["embedCss"] != null ) {
				_LoadCSS( _Settings["embedCss"] );
			}
			else if ( _ConfigurationManager.$DefaultCssUri != null ) {
				Comm.$Get( _ConfigurationManager.$DefaultCssUri
						, { onComplete : _CssManager_OnComplete, onIOError : _CssManager_OnIOError }
						);
			}
			else {
				// No se usa hoja de estilo
				_LoadIso639();
			}
		}

		/**
		 * Función que es llamada cuando se llama al gestor CSS, se ocupa de llamar a la función que carga el CSS y fallará mostrando
		 * un error en caso de que no se pueda cargar el archivo CSS
		 *
		 * @param	p_commEvent "CommEvent" que define si se ha completado bien o mal.
		 */
		private function _CssManager_OnComplete ( p_commEvent:CommEvent ) : void {
			if ( p_commEvent.$CommResponseType == CommResponseType.$TEXT ) {
				_LoadCSS( p_commEvent.$ResponseText );
			}
			else {
				trace("[ERROR] Fleaxy: El archivo de hoja de estilo especificado["+ _ConfigurationManager.$DefaultCssUri +"] no contiene el formato correcto");
			}
		}
		
		
		/**
		 * Función encargada de cargar el CSS y el idioma
		 *
		 * @param	p_css nombre del fichero CSS
		 */
		private function _LoadCSS ( p_css:String ) : void {
			_CssManager.$LoadCss( p_css );
			_LoadIso639();
		}

		
		/**
		 * Carga el archivo XML correspondiente a lidioma seleccionado en las Settings, creando un objeto "hash" que contendrá
		 * todos los textos localizados.
		 */
		private function _LoadIso639():void {
			var iso639 : String = ( _Settings["iso639"] != null ) ? _Settings["iso639"] : _ConfigurationManager.$DefaultIso639;
			if ( iso639 != null && iso639 != "" ) {
				_LocaleManager.$SetIso639(_Settings["iso639"]);

				if ( _Settings["embedIso639"][iso639] != null ) {
					var iso639Data : Object = _Settings["embedIso639"][iso639];
					if ( iso639Data is XML ) {
						_LocaleManager.$LoadFromXML( iso639Data as XML );
					}
					else { //JSON
						_LocaleManager.$LoadFromJSON( iso639Data );
					}
					_FinishInit();
				}
				else {
					var iso639Uri : String = _ConfigurationManager.$ConfigXml.SYSTEM.LOCALE.FILE.(attribute("name") == iso639).attribute( _ConfigurationManager.$Environment.toLowerCase() );
					_LocaleManager.$Load(iso639Uri, _LocaleManager_OnComplete);
				}
			}
			else {
				// No es una aplicación multiidioma
				_FinishInit();
			}
		}

		
		/**
		 * Se lanza cuando termina de cargar los textos multi idioma y detecta si ha ido bien o no.
		 *
		 * @param	p_commEvent
		 */
		private function _LocaleManager_OnComplete ( p_commEvent:CommEvent ) : void {
			if ( p_commEvent.$CommResponseType == CommResponseType.$JSON ) {
				_LocaleManager.$LoadFromJSON( p_commEvent.$ResponseJSON );
			}
			else if ( p_commEvent.$CommResponseType == CommResponseType.$XML ) {
				_LocaleManager.$LoadFromXML( p_commEvent.$ResponseXML );
			}
			
			_FinishInit();
		}

		
		/**
		 * Se lanza cuando finaliza la carga
		 */
		private function _FinishInit() : void {
			if (_Settings.hasOwnProperty("onComplete") ) {
				_Settings.onComplete();
			}
		}

		/**
		 *   Funcion que se ejecutará si falla la configuración del XML
		 *
		 * @param	p_ioErrorEvent
		 */
		private function _ConfigXml_OnIOError(p_ioErrorEvent:IOErrorEvent ) : void {
			trace("[ERROR] No se pudo cargar el fichero de configuración: " + p_ioErrorEvent.text);
		}
		
		/**
		 *   Funcion que se ejecutará si falla la configuración del CSS
		 *
		 * @param	p_ioErrorEvent
		 */
		private function _CssManager_OnIOError( p_ioErrorEvent:IOErrorEvent ) : void {
			trace("[ERROR] No se pudo cargar el fichero de estilos CSS: " + p_ioErrorEvent.text);
		}

		/**
		 * Realiza la precarga del fichero indicado
		 * @param	p_loadFile Ruta del fichero a precargar
		 * @param	f_onComplete Función
		 * @param	f_onProgress function(p_progressEvent:ProgressEvent){}
		 *
		 * @example
		 *	Fleaxy.$Preload("./fichero.swf", _Preload_OnComplete, _Preload_OnProgress );
		 */
		static public function $Preload( p_loadFile:String, f_onComplete : Function , f_onProgress : Function ) : void {
			Comm.$LoadFile( p_loadFile
						  , { onComplete : f_onComplete
							, onProgress : f_onProgress
							, onIOError : _Preload_OnIOError
						    }
						  );
		}
		
		
		/**
		 * Se encarga de detectar el error cuando la precarga falla
		 * @param	p_ioErrorEvent
		 */
		static private function _Preload_OnIOError(p_ioErrorEvent:IOErrorEvent) : void {
			trace( "[ERROR] No se pudo cargar el fichero para la precarga: " + p_ioErrorEvent.text );
		}
	}
	
}